package org.papervision3d.core.proto
{
	import org.papervision3d.core.render.command.RenderTriangle;
	import org.papervision3d.core.render.data.RenderSessionData;
	import org.papervision3d.core.render.draw.ITriangleDrawer;
	import org.papervision3d.core.render.material.MaterialManager;
	import org.papervision3d.materials.WireframeMaterial;
	import org.papervision3d.objects.DisplayObject3D;
	
	import flash.display.BitmapData;
	import flash.display.Graphics;
	import flash.events.EventDispatcher;
	import flash.geom.Matrix;
	import flash.utils.Dictionary;	

	/**
	* <span lang="ja">MaterialObject3D クラスは、全てのマテリアルの為の基本クラスです。
	* マテリアルは、レンダリングされる際、どのようにオブジェクトが現れるかについてのデータを集めます。
	* 
	* マテリアルは、オブジェクトや表面に割り当てるデータで、ラインやぬり色により、シーンの中にリアリズムを与えます。
	* さらに、オブジェクトの透過光や反射光を表現します。
	* 個別のオブジェクトや選択した表面にマテリアルを割り当てると、単一のオブジェクトは別のマテリアルを格納する事が出来ます。
	* MaterialObject3D は抽象基本クラスなので、直接呼び出すことはできません。</span>
	* 
	* <span lang="en">The MaterialObject3D class is the base class for all materials.
	* Materials collects data about how objects appear when rendered.
	* A material is data that you assign to objects or faces, so that they appear a certain way when rendered. 
	* Materials affect the line and fill colors. Materials create greater realism in a scene. 
	* A material describes how an object reflects or transmits light.
	* You assign materials to individual objects or a selection of faces; a single object can contain different materials.
	* MaterialObject3D is an abstract base class; therefore, you cannot call MaterialObject3D directly.</span>
	*/
	public class MaterialObject3D extends EventDispatcher implements ITriangleDrawer
	{
		static private var _totalMaterialObjects :Number = 0;

		/**
		* <span lang="ja">透明、または不透明な BitmapData テクスチャ</span>
		* <span lang="en">A transparent or opaque BitmapData texture.</span>
		*/
		public var bitmap :BitmapData;

		/**
		* <span lang="ja">レンダリングされる際に、BitmapData テクスチャがスムージングされるかどうかをブーリアン値で設定します。</span>
		* <span lang="en">A Boolean value that determines whether the BitmapData texture is smoothed when rendered.</span>
		*/
		public var smooth :Boolean = false;

		/**
		* <span lang="ja">レンダリングされる際に、タイル状にテクスチャリングされるかどうかをブーリアン値で設定します。デフォルトは false です。</span>
		* <span lang="en">A Boolean value that determines whether the texture is tiled when rendered. Defaults to false.</span>
		*/
		public var tiled :Boolean = false;

		/**
		* <span lang="ja">テクスチャーがキャッシュされるかどうかをブーリアン値で設定します。つまり、レンダリングされる前にアップデートされます。デフォルトは false です。</span>
		* <span lang="en">A Boolean value that determines whether the texture is cached, i.e. not updated before being rendered. Defaults to false.</span>
		*/
		public var baked :Boolean = false;

		/**
		* <span lang="ja">表面の輪郭を描く RGB カラー値</span>
		* <span lang="en">A RGB color value to draw the faces outline.</span>
		*/
		public var lineColor :Number = DEFAULT_COLOR;

		/**
		* <span lang="ja">表面の輪郭の為の8ビットアルファ値です。ゼロのとき、輪郭は描かれません。</span>
		* <span lang="en">An 8-bit alpha value for the faces outline. If zero, no outline is drawn.</span>
		*/
		public var lineAlpha :Number = 0;
		
		/**
		* <span lang="ja">輪郭の厚さの為の値。</span>
		* <span lang="en">An value for the thickness of the faces line.</span>
		*/
		public var lineThickness:Number = 1;

		/**
		* <span lang="ja">表面を塗るRGBカラー値。テクスチャが提供されていない場合のみ使用される。</span>
		* <span lang="en">A RGB color value to fill the faces with. Only used if no texture is provided.</span>
		*/
		public var fillColor :Number = DEFAULT_COLOR;

		/**
		* <span lang="ja">表面を塗る8ビットアルファ値。この値がゼロで、テクスチャが提供されていない、又は未定義のとき、塗りは作成されません。</span>
		* <span lang="en">An 8-bit alpha value fill the faces with. If this value is zero and no texture is provided or is undefined, a fill is not created.</span>
		*/
		public var fillAlpha :Number = 0;

		/**
		* <span lang="ja">表面が片側のみかどうかを指定するブーリアン値です。両面を優先します。</span>
		* <span lang="en">A Boolean value that indicates whether the faces are single sided. It has preference over doubleSided.</span>
		*/
		public var oneSide :Boolean = true;

		/**
		* <span lang="ja">表面が不可視化される（描かれない）かどうかを指定するブーリアン値です。</span>
		* <span lang="en">A Boolean value that indicates whether the faces are invisible (not drawn).</span>
		*/
		public var invisible :Boolean = false;

		/**
		* <span lang="ja">表面が反転されるかどうかを指定するブーリアン値です。doubleSidedか、singleSidedではない時のみに使用されます。</span>
		* <span lang="en">A Boolean value that indicates whether the face is flipped. Only used if doubleSided or not singeSided.</span>
		*/
		public var opposite :Boolean = false;

		/**
		* <span lang="ja">デフォルトマテリアルに使用される色です。</span>
		* <span lang="en">Color used for DEFAULT material.</span>
		*/
		static public var DEFAULT_COLOR :int = 0x000000;

		/**
		* <span lang="ja">デバッグマテリアルに使用される色です。</span>
		* <span lang="en">Color used for DEBUG material.</span>
		*/
		static public var DEBUG_COLOR :int = 0xFF00FF;

		/**
		* <span lang="ja">マテリアルの名前です。</span>
		* <span lang="en">The name of the material.</span>
		*/
		public var name :String;

		/**
		* <span lang="ja">[internal-use] [読み取り専用] このインスタンスのユニーク id です。</span>
		* <span lang="en">[internal-use] [読み取り専用] Unique id of this instance.</span>
		*/
		public var id :Number;

		/**
		 * 
		 * Internal use
		 */
		public var maxU :Number;

		/**
		 * 
		 * Internal use
		 */
		public var maxV :Number;
		 
		 /**
		* <span lang="ja">オートミップマッピングによって、リサイズされる前にビットマップのオリジナルサイズを保持します。</span>
		* <span lang="en">Holds the original size of the bitmap before it was resized by Automip mapping</span>
		*/
		 public var widthOffset:Number = 0;
		/**
		* <span lang="ja">オートミップマッピングによって、リサイズされる前にビットマップのオリジナルサイズを保持します。</span>
		* <span lang="en">Holds the original size of the bitmap before it was resized by Automip mapping</span>
		*/
		 public var heightOffset:Number = 0;
		
		/**
		 * <span lang="ja">このマテリアルがインタラクティブになるかどうか定義します。</span>
		 * <span lang="en">Defines if this material will be interactive</span>
		 */
		public var interactive:Boolean = false;

		/**
		 * <span lang="ja">格納されたオブジェクトの全てのリストです。</span>
		 * <span lang="en">Inventory of registered objects</span>
		 */
		protected var objects:Dictionary;

		/**
		* <span lang="ja">新しい MaterialObject3d オブジェクトを作成します。</span>
		* <span lang="en">Creates a new MaterialObject3D object.</span>
		*
		*/
		public function MaterialObject3D()
		{
			this.id = _totalMaterialObjects++;
			MaterialManager.registerMaterial(this);
			objects = new Dictionary(true);
		}

		/**
		* <span lang="ja">デフォルトのマゼンタワイヤーフレームで MaterialObject3D オブジェクトを取得します。</span>
		* <span lang="en">Returns a MaterialObject3D object with the default magenta wireframe values.</span>
		*
		* @return A MaterialObject3D object.
		*/
		static public function get DEFAULT():MaterialObject3D
		{
			var defMaterial :MaterialObject3D = new WireframeMaterial(); //RH, it now returns a wireframe material.
			defMaterial.lineColor   = 0xFFFFFF * Math.random();
			defMaterial.lineAlpha   = 1;
			defMaterial.fillColor   = DEFAULT_COLOR;
			defMaterial.fillAlpha   = 1;
			defMaterial.doubleSided = false;

			return defMaterial;
		}

		static public function get DEBUG():MaterialObject3D
		{
			var defMaterial :MaterialObject3D = new MaterialObject3D();

			defMaterial.lineColor   = 0xFFFFFF * Math.random();
			defMaterial.lineAlpha   = 1;
			defMaterial.fillColor   = DEBUG_COLOR;
			defMaterial.fillAlpha   = 0.37;
			defMaterial.doubleSided = true;

			return defMaterial;
		}
		
		
		/**
		 * <span lang="ja">スクリーンに三角形を描きます。</span>
		 * <span lang="en">Draws the triangle to screen.</span>
		 */
		public function drawTriangle(tri:RenderTriangle, graphics:Graphics, renderSessionData:RenderSessionData, altBitmap:BitmapData = null, altUV:Matrix = null):void
		{
			
		}
		
		public function drawRT(rt:RenderTriangle, graphics:Graphics, renderSessionData:RenderSessionData):void{
			
		}
		
		/**
		* <span lang="ja">与えられたテクスチャから BitmapData のビットマップをアップデートする。
		* ビットマップに最新の MovieClip イメージをを描写します。</span>
		* 
		* <span lang="en">Updates the BitmapData bitmap from the given texture.
		* Draws the current MovieClip image onto bitmap.</span>
		*/
		public function updateBitmap():void {}


		/**
		* <span lang="ja">マテリアルのプロパティをコピーします。</span>
		* 
		* <span lang="en">Copies the properties of a material.</span>
		*
		* @param	material	Material to copy from.
		*/
		public function copy( material :MaterialObject3D ):void
		{
			this.bitmap    = material.bitmap;
			this.smooth    = material.smooth;

			this.lineColor = material.lineColor;
			this.lineAlpha = material.lineAlpha;
			this.fillColor = material.fillColor;
			this.fillAlpha = material.fillAlpha;
			
			this.oneSide   = material.oneSide;
			this.opposite  = material.opposite;

			this.invisible = material.invisible;
			this.name      = material.name;
			
			this.maxU      = material.maxU;
			this.maxV      = material.maxV;
		}

		/**
		* <span lang="ja">マテリアルのコピーを作成します。</span>
		* 
		* <span lang="en">Creates a copy of the material.</span>
		*
		* @return	A newly created material that contains the same properties.
		*/
		public function clone():MaterialObject3D
		{
			var cloned:MaterialObject3D = new MaterialObject3D();
			cloned.copy(this);
			return cloned;
		}
		
		/**
		 * <span lang="ja">DisplayObject3D を登録します。</span>
		 * 
		 * <span lang="en">Registers the <code>DisplayObject3D</code></span>
		 */
		
		public function registerObject(displayObject3D:DisplayObject3D):void
		{
			objects[displayObject3D] = true;
		}
		
		public function unregisterObject(displayObject3D:DisplayObject3D):void
		{
			if(objects && objects[displayObject3D] ){
				objects[displayObject3D] = null;
			}
		}
		
		public function destroy():void
		{
			objects = null;
			bitmap = null;
			MaterialManager.unRegisterMaterial(this);
		}

		/**
		* <span lang="ja">マテリアルのプロパティを表わした string 値を取得します。</span>
		* 
		* <span lang="en">Returns a string value representing the material properties.</span>
		*
		* @return	A string.
		*/
		override public function toString():String
		{
			return '[MaterialObject3D] bitmap:' + this.bitmap + ' lineColor:' + this.lineColor + ' fillColor:' + fillColor;
		}
		
		/**
		* <span lang="ja">表面が double sided かどうか指定するブーリアン値です。</span>
		* 
		* <span lang="en">A Boolean value that indicates whether the faces are double sided.</span>
		*/
		public function get doubleSided():Boolean
		{
			return ! this.oneSide;
		}

		public function set doubleSided( double:Boolean ):void
		{
			this.oneSide = ! double;
		}

		/**
		* <span lang="ja">マテリアルで登録された DisplayObject3D のリストを取得します。</span>
		* 
		* <span lang="en">Returns a list of <code>DisplayObject3D</code> objects registered with the material.</span>
		*/
		public function getObjectList():Dictionary
		{
			return objects;
		}
		
		public function isUpdateable():Boolean
		{
			return ! baked;
		}
	}
}
